use crate::{kisserr, Cli};
use crate::bcossdk::kisserror::{KissError,KissErrKind};
use crate::bcossdk::bcossdk::BcosSDK;
use std::str::FromStr;
use serde_json::{Value as JsonValue};
use crate::bcossdk::contracthistory::ContractHistory;
use crate::bcossdk::contractabi::ContractABI;
use crate::bcossdk::commonhash::CommonHash;
use ethabi::Log;
use crate::bcossdk::bcosclientconfig::{BcosCryptoKind, ClientConfig};
use secp256k1::ffi::secp256k1_context_no_precomp;
use crate::console::console_utils::{display_transaction_receipt, display_transaction, find_contracthistory_byaddress, find_contract, is_deploy_address};
use crate::bcossdk::bcossdkquery::json_hextoint;

pub fn handle_cmd(cmd:&str, params:&Vec<String>, configfile:&str,cli:&Cli) ->Result<(),KissError>
{
    let mut bcossdk = BcosSDK::new_from_config(configfile)?;
    println!("BcosSDK: {}",bcossdk.to_summary());
    match cmd {
        "getBlockNumber"=>{
            let v = bcossdk.getBlockNumber()?;
            println!("\n[{}] : {:?}\n",cmd,v);
            Ok(())
        },
        "getNodeVersion"=>{
            let v = bcossdk.getNodeVersion()?;
            println!("\n[{}] : {}\n",cmd,serde_json::to_string_pretty(&v).unwrap());
            Ok(())
        },
        "getBlockByNumber"=>{
            let num = u32::from_str_radix(params[0].as_str(),10).unwrap();
            let mut includeTransactions = true;
            if params.len() > 1 {
                includeTransactions = bool::from_str(params[1].as_str()).unwrap();
            }
            let v = bcossdk.getBlockByNumber(num,includeTransactions)?;
            println!("\n[{}] : {}\n",cmd,serde_json::to_string_pretty(&v).unwrap());
            Ok(())
        },
        "getBlockByHash"=>{
            let hash =params[0].as_str();
            let mut includeTransactions = true;
            if params.len() > 1 {
                includeTransactions = bool::from_str(params[1].as_str()).unwrap();
            }
            let v = bcossdk.getBlockByHash(hash,includeTransactions)?;
            println!("\n[{}] : {}\n",cmd,serde_json::to_string_pretty(&v).unwrap());
            Ok(())
        },
        "getTransactionByHash"=>{
            cmd_getTransactionByHash(&mut bcossdk,&params,&cli)
        }
        "getTransactionReceipt"=>{
            cmd_getTransactionReceipt(&mut bcossdk,&params,&cli)
        }
        "getTransactionByBlockHashAndIndex"=>{
            cmd_getTransactionByBlockHashAndIndex(&mut bcossdk,&params,&cli)
        }
        "getTransactionByBlockNumberAndIndex"=>{
            cmd_getTransactionByBlockNumberAndIndex(&mut bcossdk,&params,&cli)
        }
        _=>{
            kisserr!(KissErrKind::Error,"cmd {} not implement",cmd)
        }
    }
}

pub fn cmd_getTransactionByHash(bcossdk:&mut BcosSDK,params:&Vec<String>,cli:&Cli)->Result<(),KissError>{
    let cmd ="getTransactionByHash";
    let hash = params[0].as_str();
    let v  = bcossdk.getTransactionByHash(hash)?;
    let res = display_transaction(&v,bcossdk,&cli);
    Ok(())
}

pub fn cmd_getTransactionReceipt(bcossdk:&mut BcosSDK,params:&Vec<String>,cli:&Cli)->Result<(),KissError> {
    let cmd = "getTransactionReceipt";
    let hash = params[0].as_str();
    let v = bcossdk.getTransactionReceipt(hash)?;
    println!("\n[{}] : {}\n", cmd, serde_json::to_string_pretty(&v).unwrap());
    if v["result"] == JsonValue::Null
    {
        println!("reuslt is Null");
        return Ok(())
    }
    let to = v["result"]["to"].as_str().unwrap();
    if is_deploy_address(to){
        let blocknum = json_hextoint(&v["result"]["blockNumber"]).unwrap();
        println!("is a deploy contract transaction on block [{}]",blocknum);
        return Ok(());
    }

    let contractres = find_contract(&cli.contractname,to,&bcossdk.config);
    let contract = match contractres {
                    Ok(c) => { c },
                    Err(e) => {
                        //miss ,but maybe not a error
                        println!("Missing contract history for address  [{}] ,but ok &done ", to);
                        return Ok(())
                    }
                };
    display_transaction_receipt(&v,&contract,&bcossdk.config);
    Ok(())
}

pub fn cmd_getTransactionByBlockNumberAndIndex(bcossdk:&mut BcosSDK,params:&Vec<String>,cli:&Cli)->Result<(),KissError>{

    let cmd ="getTransactionByBlockNumberAndIndex";
    let num = u32::from_str_radix( params[0].as_str() , 10).unwrap();
    let index  = u32::from_str_radix( params[1].as_str() , 10).unwrap();
    let v  = bcossdk.getTransactionByBlockNumberAndIndex(num,index)?;
    let res = display_transaction(&v,bcossdk,&cli);
    Ok(())
}

pub fn cmd_getTransactionByBlockHashAndIndex(bcossdk:&mut BcosSDK,params:&Vec<String>,cli:&Cli)->Result<(),KissError>{

    let cmd ="getTransactionByBlockNumberAndIndex";
    let blockhash = params[0].as_str();
    let index  = u32::from_str_radix( params[1].as_str() , 10).unwrap();
    let v  = bcossdk.getTransactionByBlockHashAndIndex(blockhash,index)?;
    let res = display_transaction(&v,bcossdk,&cli);
    Ok(())
}
